PROF-1037: Capture thread CPU time elapsed in scope#1358
Conversation
devinsba
left a comment
There was a problem hiding this comment.
Makes sense to me. We might want to check that JFR is supported before making the initialize call to save a class load
|
|
||
| @Label("Thread CPU Time") | ||
| @Timespan | ||
| private volatile long cpuTime = 0L; |
There was a problem hiding this comment.
My impression is that scopes are locked to given thread - is there any point in this being volatile?
There was a problem hiding this comment.
If it is guaranteed that the event is created and committed from the same thread then this does not need to be volatile. I just wasn't sure there was such a guarantee.
mar-kolya
left a comment
There was a problem hiding this comment.
It would be really great to have new code tested.
In addition to requests already mentioned in the comments I think it would be possible to have integration test for profiling improved to have some verification that we are getting reasonable data in new event.
|
@devinsba The check would be quite tricky without reworking the initialization logic in In the current implementation we first fire up I would really like to avoid major rewrite of initialization protocol for EDIT: Actually, scratch this. I was able to come up with something simple with @mar-kolya help so we might be good to go regarding not loading this class unnecessarily. |
| * Initialize the thread cpu time provider only if profiling is enabled. | ||
| * ATTENTION! If ever is the thread cpu time provider used outside of profiler this check should be revisited. | ||
| */ | ||
| if (Config.get().isProfilingEnabled()) { |
There was a problem hiding this comment.
We do not use Config here - and IIRC there are awkward implications for doing that. Could you please move this check into datadog.trace.common.util.ThreadCpuTimeAccess#enableJmx?
There was a problem hiding this comment.
Well, I thought the idea was to avoid loading that class at all :)
| attribute = k | ||
| } | ||
| } | ||
| return attribute |
There was a problem hiding this comment.
Would def accessor = Attribute.attr("cpuTime", UnitLookup.TIMESPAN).getAccessor(scopeEventIterable.type) work instead of this?
There was a problem hiding this comment.
D'oh ... Yes, it works.
|
LGTM assuming it builds |
| end(); | ||
| if (shouldCommit()) { | ||
| if (cpuTime > 0) { | ||
| cpuTime = ThreadCpuTimeAccess.getCurrentThreadCpuTime() - cpuTime; |
There was a problem hiding this comment.
Any risk of finish() being called more than once?
There was a problem hiding this comment.
It is called solely from ContinuableScope.close() so as long as that scope is not closed multiple times we are fine.
There was a problem hiding this comment.
I'd say that if this happens things will not blow up but data we produce would be off. But arguably this is the best we can do in this situation anyway.
Add thread CPU time elapsed while the scope was active to the Scope event.
Thread CPU time is comparatively cheap to obtain (~300ns per inocation) so we should be able to enhance the Scope event with the amount of CPU time spent in each recorded scope.